﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace MSI2
{
    public partial class MainForm : Form
    {
        public static int NumberOfAminoAcids = 21; //liczba aminokawsów - 20 + "pusty"
        public static int FirstLevelWindowSize = 13; //długość "okna":  13-21
        public static int SecondLevelWindowSize = 17;
        public static int AminoLength; //długość białka
        public static double Gamma = 0.5;
        public static double Beta = 0.1;
        public static int HiddenLayerSize = 6;
        public static int OutputLayerSize = 3;

        public static string InputFile;
        public static string FirstLayerFile;
        public static string SecondLayerFile;
        public static bool IsTraining = false;
        public static bool CreateNewNetwork = false;

        private List<ParsedData> _data;
        private bool working;
        private bool[] dataLoaded = new bool[3];
        public static string outputFile = "output.txt";

        public MainForm()
        {
            InitializeComponent();
        }

        private void button1_Click_1(object sender, EventArgs e)
        {
            var fd = new OpenFileDialog();

            var result = fd.ShowDialog();

            if (!String.IsNullOrEmpty(fd.FileName))
            {
                InputFile = fd.FileName;
            }


            WriteLine("Loading data from file " + InputFile + "...");

            var parser = new Parser(InputFile);
            _data = parser.LoadData();

            if (_data == null)
                WriteLine("Could not load data from file: " + InputFile + " !");
            else
            {
                WriteLine("Data loaded!: " + _data.Count + " aminos loaded!");
                dataLoaded[0] = true;
                checkStart();
            }

        }

        private void checkStart()
        {
            for (int i = 0; i < dataLoaded.Length; i++)
            {
                if (!dataLoaded[i] && !checkBox2.Checked)
                {
                    button2.Enabled = false;
                    return;
                }
            }
            button2.Enabled = true;
        }

        private void WriteLine(string text)
        {
            textBox1.Text += text + "\n";
        }

        private void button3_Click(object sender, EventArgs e)
        {
            var fd = new OpenFileDialog();

            var result = fd.ShowDialog();

            if (!String.IsNullOrEmpty(fd.FileName))
            {
                FirstLayerFile = fd.FileName;
                dataLoaded[1] = true;
                checkStart();
            }
        }

        private void button4_Click(object sender, EventArgs e)
        {
            var fd = new OpenFileDialog();

            var result = fd.ShowDialog();

            if (!String.IsNullOrEmpty(fd.FileName))
            {
                SecondLayerFile = fd.FileName;
                dataLoaded[2] = true;
                checkStart();
            }
        }

        private void button2_Click(object sender, EventArgs e)
        {
            working = true;
            setEnabled(false);

            CreateNewNetwork = checkBox2.Checked;
            IsTraining = checkBox1.Checked;
            progressBar1.Value = 0;

            var first = new NeuralNetwork.NeuralNetworkParams
            {
                Beta = Beta,
                Gamma = Gamma,
                HiddenLayerSize = HiddenLayerSize,
                InputLayerSize = NumberOfAminoAcids * FirstLevelWindowSize,
                OutputLayerSize = OutputLayerSize
            };

            var second = new NeuralNetwork.NeuralNetworkParams
            {
                Beta = Beta,
                Gamma = Gamma,
                HiddenLayerSize = HiddenLayerSize,
                InputLayerSize = OutputLayerSize * SecondLevelWindowSize,
                OutputLayerSize = OutputLayerSize
            };

            var phdSec = new PhdSec(first, second);

            if (!CreateNewNetwork)
            {
                phdSec.Load(FirstLayerFile, SecondLayerFile);
            }
            else
            {
                WriteLine("New network created");
            }

            double avg = 0.0;
            int progress = -1;

            File.Delete(outputFile);
            var streamWriter = new StreamWriter(outputFile, true);

            int correctAns = 0, totalAns = 0;

            for (int i = 0; i < _data.Count; i++)
            {
                if (!working)
                    break;

                var current = (int)((double)i * 100 / _data.Count);
                if (current > progress)
                {
                    progress = current;
                    progressBar1.Value = current;
                }
                AminoLength = _data[i].Sequence.Length / 21;
                var input = _data[i].Sequence;
                var output = _data[i].Structure;
                phdSec.Run(IsTraining, input, output, AminoLength);
                double score = phdSec.ComputeScore(_data[i].Structure, ref correctAns, ref totalAns);
                phdSec.SaveOutput(_data[i], streamWriter);
                // if (score >= 100 || Double.IsNaN(score) || Double.IsPositiveInfinity(score)) continue;
                avg += score;
            }

            streamWriter.Close();

            if (IsTraining)
                phdSec.Save(FirstLayerFile, SecondLayerFile);

            WriteLine("Total score: " + (double)100 * correctAns / totalAns);
            WriteLine(" Output was saved in file: " + outputFile);

            setEnabled(true);
            progressBar1.Value = 100;
        }

        private void setEnabled(bool value)
        {
            this.button1.Enabled = value;
            this.button2.Enabled = value;
            this.button3.Enabled = value;
            this.button4.Enabled = value;
            this.checkBox1.Enabled = value;
            this.checkBox2.Enabled = value;

            this.stopButton.Enabled = !value;
            if (!value)
            {
                this.progressBar1.Value = 1;
            }
        }

        private void stopButton_Click(object sender, EventArgs e)
        {
            working = false;
        }

        private void checkBox2_CheckedChanged(object sender, EventArgs e)
        {
            checkStart();
        }
    }
}
